import {useState, forwardRef, useImperativeHandle} from "react";
import { AxiosProgressEvent } from 'axios'
import {Button, Drawer, List, Popover, Progress, Upload, UploadFile, UploadProps} from "antd";
import { CloudUploadOutlined } from '@ant-design/icons';
import isMobile from "@/utils/isMobile.ts";
import {useSearchParams} from "react-router-dom";
import {uploadFile} from "@/api/upload.ts";

const { Dragger } = Upload;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
declare const ProgressStatuses: readonly ["normal", "exception", "active", "success"];
interface IProps {
    refresh: () => void
}
interface IData { uid: string, size: number, name: string, percent: number, status: (typeof ProgressStatuses[number]) }

const FileDrawer = forwardRef(({ refresh }: IProps, ref) => {
    const [open, setOpen] = useState(false);
    const [dataProgress, setDataProgress] = useState<Array<IData>>([])
    const [fileLists, setFileLists] = useState<Array<UploadFile>>([])
    const [fileItem, setFileItem] = useState<UploadFile | null>(null)
    const [searchParams] = useSearchParams()
    const changeOpen = (bool: boolean) => {
        setOpen(bool)
        if (!bool) {
            refresh()
        }
    }
    const changeFile: UploadProps['onChange'] = (info) => {
        const { fileList, file } = info
        setFileItem(file)
        setFileLists(fileList)
        setDataProgress(fileList.map(item => ({ uid: item.uid, name: (item.originFileObj as File).name, percent: 0, status: 'active', size: (item.originFileObj as File).size })))
    }
    const customRequest = async () => {
        const data = new FormData()
        data.append('file', (fileItem as UploadFile).originFileObj as File)
        data.append('parentFileUID', searchParams.get('fileUID') || '0')
        data.append('fileName', ((fileItem as UploadFile).originFileObj as File).name)
        data.append('state', '0')
        try {
            await uploadFile(data, (progressEvent: AxiosProgressEvent) => {
                if (progressEvent.lengthComputable) {
                    const percentComplete: number = (progressEvent.loaded / (progressEvent as { total: number }).total) * 100;
                    setDataProgress(dataProgress.map(item => {
                        if (item.uid === (fileItem as UploadFile).uid) {
                            item.percent = percentComplete
                        }
                        return item
                    }))
                }
            })
        } catch {
            setDataProgress(dataProgress.map(item => {
                if (item.uid === (fileItem as UploadFile).uid) {
                    item.status = 'exception'
                }
                return item
            }))
        }
        setFileLists([])
    }
    const clear = () => {
        setDataProgress(dataProgress.filter(item => item.percent !== 100))
    }
    useImperativeHandle(ref, () => ({ changeOpen }))
    return (
        <div>
            <Drawer width={isMobile() ? 300 : 500} title="上传文件" placement='right' closable={false} onClose={() => changeOpen(false)} open={open} key='right'>
                <>
                    <div style={{ marginBottom: '20px', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
                        <span>上传任务：{`${dataProgress.filter(item => item.percent !== 0).length}/${dataProgress.length}`}</span>
                        <span style={{ color: '#42b983' }}>成功：{dataProgress.map(item => item.percent === 100).length}</span>
                        <span style={{ color: '#ff5a5f' }}>失败：0</span>
                        <Button type='text' danger onClick={clear}>清除已完成</Button>
                    </div>
                    <div style={{height: '200px'}}>
                        <Dragger customRequest={customRequest} multiple={false} onChange={changeFile}
                                 fileList={fileLists}>
                            <p className="ant-upload-drag-icon"><CloudUploadOutlined/></p>
                            <p className="ant-upload-text">将文件拖拽到此处，或者点击选择文件</p>
                            <p className="ant-upload-hint">可以选择多个文件进行上传</p>
                        </Dragger>
                    </div>
                    {
                        dataProgress.length !== 0 ? <List style={{ marginTop: '20px' }} bordered dataSource={dataProgress}
                              renderItem={(item: IData) => (
                                  <List.Item>
                                      <List.Item.Meta
                                          title={<Popover content={`${item.name}(${parseFloat((item.size / (1024 * 1024)).toFixed(2))}MB)`}>
                                              <div style={{
                                                  overflow: 'hidden',
                                                  textOverflow: 'ellipsis',
                                                  whiteSpace: 'nowrap'
                                              }}>{`${item.name}(${parseFloat((item.size / (1024 * 1024)).toFixed(2))}MB)`}</div>
                                          </Popover>}
                                          description={<div>
                                              <Progress percent={parseFloat(item.percent.toFixed(2))}
                                                        status={item.status === 'exception' ? 'exception' : parseInt(String(item.percent)) === 100 ? 'success' : 'active'} />
                                              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
                                                  <span>{`${parseFloat((item.size / (1024 * 1024)).toFixed(2))}MB`}</span>
                                                  <span>{parseInt(String(item.percent)) === 100 ? '上传成功' : '上传中'}</span>
                                              </div>
                                          </div>}
                                      />
                                  </List.Item>
                              )}
                        /> : null
                    }
                </>
            </Drawer>
        </div>
    )
})

export default FileDrawer